#include "osMemblock.h"

#include "osCpu.h"


#if OS_ENABLE_MEMBLOCK == 1

/*****************************************************************************
 * @function        vMemBlockInit
 * @brief 			初始化存储区控制块.
 *  
 * @param[in] 		memBlock 存储区控制块.
 * @param[in]       memStart 存储区首地址.
 * @param[in] 	    blockSize 存储块大小.
 * @param[in] 	    maxCount 存储块数量.
 * 
 * @return 			None.	
 *
 * ***************************************************************************/
void vMemBlockInit(MEMBLOCK_T *memBlock, uint8_t * memStart, uint32_t blockSize, uint32_t maxCount)
{
    uint8_t *memBlockStart = memStart;
    uint8_t *memBlockEnd = memBlockStart + blockSize * maxCount;
    
    if (blockSize < sizeof(NODE_T))
    {
        return ;
    }
    
    vEventInit(&memBlock->event, eventTypeMemBlock);
    memBlock->memStart = memStart;
    memBlock->blockSize = blockSize;
    memBlock->maxCount = maxCount;
    vListInit(&memBlock->blockList);
    
    while (memBlockStart < memBlockEnd)
    {
        vNodeInit((NODE_T *)memBlockStart);
        vListAddLast(&memBlock->blockList, (NODE_T *)memBlockStart);
        
        memBlockStart += blockSize;
    }
}


/*****************************************************************************
 * @function        vMemBlockWait
 * @brief 			等待获取存储块.
 *  
 * @param[in] 		memblock 存储区控制块.
 * @param[out]      mem 获得的存储块.
 * @param[in] 	    timeout 等待时间.
 * 
 * @return 			返回获取存储块的结果. 	OS_NOERROR:获取成功     
*                          OS_TIMEOUT : 等待获取超时
 *
 * ***************************************************************************/
uint32_t vMemBlockWait(MEMBLOCK_T *memblock, uint8_t **mem, uint32_t timeout)
{
    uint32_t primask = vTaskEnterCritical();
    
    /* 有空闲的存储块---> 直接给任务*/
    if (vListCount(&memblock->blockList) != 0)
    {
        
        *mem = (uint8_t *)vListRemoveFirst(&memblock->blockList);
        vTaskExitCritical(primask);
        
        return OS_NOERROR;
    }
    /* 无空闲存储块--->任务进入事件等待队列*/
    else 
    {
        vEventWait(&memblock->event, curTask, (void *) 0, OS_TASK_STA_WAIT_MEM, timeout);
        vTaskExitCritical(primask);
        
        vTaskYield();
        
        /* 任务就绪后，会在此执行*/
        *mem = curTask->eventMsg;
        return curTask->waitEventResult;
    }
}


/*****************************************************************************
 * @function        vMemBlockWait
 * @brief 			获取存储块（非阻塞）.
 *  
 * @param[in] 		memblock 存储区控制块.
 * @param[out]      mem 获得的存储块.
 * 
 * @return 			返回获取存储块的结果. 	OS_NOERROR:获取成功  
 *                      OS_ERROR_NORESOURCE : 无空闲存储块资源    
 *
 * ***************************************************************************/
uint32_t vMemBlockNoWait(MEMBLOCK_T *memblock, uint8_t **mem)
{
    uint32_t primask = vTaskEnterCritical();
    
    /* 有空闲的存储块---> 直接给任务*/
    if (vListCount(&memblock->blockList) != 0)
    {
        *mem = (uint8_t *)vListFirst(&memblock->blockList);
        vTaskExitCritical(primask);
        
        return OS_NOERROR;
    }
    /* 无空闲存储块--->任务进入事件等待队列*/
    else 
    {
        vTaskExitCritical(primask);
        return OS_ERROR_NORESOURCE;
    }
}


/*****************************************************************************
 * @function        vMemBlockNotify
 * @brief 			释放存储块.
 *  
 * @param[in] 		memblock 存储区控制块.
 * @param[in]       mem 待释放的存储块指针.
 * 
 * @return 			None.	
 *
 * ***************************************************************************/
void vMemBlockNotify(MEMBLOCK_T *memblock, uint8_t *mem)
{
    TASK_T *task;
    uint32_t primask = vTaskEnterCritical();
    
    /* 如果 存储区 事件等待队列中有任务*/
    if (vEventWaitCount(&memblock->event) != 0)
    {
        task = vEventWakeUp(&memblock->event, mem, OS_NOERROR);
        vTaskExitCritical(primask);
        
        
        if (task->prio < curTask->prio)
        {
            vTaskYield();
        }
    }
    /* 无任务等待，将存储块放入 存储队列中*/
    else 
    {
        vListAddLast(&memblock->blockList, (NODE_T *)mem);
        vTaskExitCritical(primask);
    }

}



/*****************************************************************************
 * @function        vMemBlockGetInfo
 * @brief 			获取存储区控制块的信息.
 *  
 * @param[in] 		memblock 存储区控制块.
 * @param[in]       info 存储区信息结构体.
 * 
 * @return 			None.	
 *
 * ***************************************************************************/
void vMemBlockGetInfo(MEMBLOCK_T *memblock, MEMBLOCK_INFO_T *info)
{
    uint32_t primask = vTaskEnterCritical();
    
    info->blockSize = memblock->blockSize;
    info->maxCount = memblock->maxCount;
    info->taskCount = vEventWaitCount(&memblock->event);
    info->count = vListCount(&memblock->blockList);
    
    vTaskExitCritical(primask);
}


/*****************************************************************************
 * @function        vMemBlockGetInfo
 * @brief 			删除存储区中等待获取控制块的所有任务.
 *  
 * @param[in] 		memblock 存储区控制块.
 * 
 * @return 			被释放的任务数量.	
 *
 * ***************************************************************************/
uint32_t vMemBlockDestroy(MEMBLOCK_T *memblock)
{
    uint32_t count;
    uint32_t primask = vTaskEnterCritical();
    
    count = vEventRemoveAll(&memblock->event, (void *)0, OS_FORCE_DEL);

    vTaskExitCritical(primask);
    
    if (count > 0)
    {
        vTaskYield();
    }
    
    return count;
    
}

#endif // OS_ENABLE_MEMBLOCK == 1

